feat(manager): worlds — the parts of a life, and the faces in them - #212
Merged
Conversation
Three calls against the family specified in dtgwg-trust-tasks-tf#405 and published in @openvtc/trust-tasks 0.17.9 (the dependency moves from ^0.17.8, which cannot name these types). On screen these are **worlds** — `design-docs/persona-vocabulary.md`. The wire keeps the specification's word, exactly as `profile`/face does. **Membership is sent only where the caller supplied it.** Both lists are REPLACED by a put, so sending `[]` for a caller that passed nothing would empty a facet's membership on an edit that meant to rename it — the same replace hazard the attribute editor guards one record down. The paired assertion matters as much: an explicitly empty list IS carried, because a suite that only checks omissions passes for a client that never sends membership at all. **The listing follows the cursor.** `limit` is the page size to ask for and never a cap, the fourth listing in this module to say so and for the same reason: a short page is indistinguishable from a complete one, so only an absent `nextCursor` means the end. **Delete sends the facet and nothing else.** There is no cascade member anywhere on this wire — a facet is an arrangement, not a container — and `releasedFaces` is what a surface needs to describe the result honestly rather than saying only "deleted". `FacetColour` is re-exported from the generated bindings rather than derived by indexed access: `package.no-restated-types.mjs` catches the second, and it is right to — a local restatement of an enum drifts silently the moment a ninth colour is published. Both CI guard lists grow from ten URIs to thirteen: the exclusion that keeps this half out of every wallet surface, and the presence assertion that keeps the console from losing it to a dropped import or a tree-shake. core 595/596. The one failure is `task-surface.mjs`: the snapshot is synced from a vta-sdk checkout and records the crate VERSION, so syncing it from the unmerged branch carrying these constants (OpenVTC/verifiable-trust-infrastructure#1338) would record that a published vta-sdk contains tasks it does not. It is synced from main, as its own reviewed commit, once that merges. Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
`manager-theme.css` sets the rule that `--w-ok` / `--w-warn` / `--w-danger` are the only colours that mean anything. A world colour is the third categorical set, and the first one in this console chosen by a **person** — which is exactly what makes it worth asserting rather than eyeballing. Given a free-form hex from a holder, nothing could keep a decorative choice out of the semantic channel: someone names a world "Work", picks red, and every card in it reads as an alarm with no way to discover why. A closed set of eight makes that unrepresentable rather than merely discouraged. `manager-world-colour.test.mts` computes the distance from the values the stylesheet actually ships — not from a copy kept in the test, which would pass forever after someone edited the CSS — per theme, because a light world colour sitting far from the light danger red says nothing about the dark pair and both ship. Closest legitimate pair is 69.6 (sand vs warn, dark) against a threshold of 60. **Verified non-vacuous**: moving `--m-world-clay` to #b03d2d fails the test with "is 9.0 from --w-danger … a holder picking it would have every card in that world read as danger". `WORLD_COLOURS` is typed against the generated `FacetColour` union, so a ninth colour published in the specification is a compile error here — a picker missing an option the agent will happily store — rather than a name this console silently cannot draw. `worldHue` returns a token reference and never a value, because a component reaching for a hex is correct in exactly one theme. Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
The console's half of `persona/facet/*`, behind a third view on the persona pane. A holder who uses this model for a while does not end up with three faces; they end up with twenty, and a flat list of twenty is a list nobody reads. **The delete confirm is the whole screen.** A grouping that looks like a folder is assumed to behave like one, so the confirm names what *survives* before what goes: "All 2 faces in it — Acme, LinkedIn — stay exactly as they are." A holder who believes Delete takes the faces with it will not press it; one who believes it and is wrong has lost nothing and will never trust the screen again. There is no cascade on the wire and none is implied — `worlds-pane.render.test.mts` asserts both the survival sentence and the absence of any "also delete" copy. **A face already elsewhere is greyed before the save, not refused after.** A checkbox that looked available and then failed is a refusal the holder had no way to anticipate. `worldOfFace` excludes the world being edited, or a world becomes uneditable the moment it holds anything. **The refusal is matched on the code, and typed on the class that carries one.** `placedElsewhere` tests `instanceof RelayTaskError` and `code === "persona/facet/put:faceAlreadyPlaced"` — R3.7, never a message. A refusal whose details are missing or half-typed returns null rather than an empty list: "0 faces already belong elsewhere" is a claim, and half an answer about where the holder's faces are is worse than none because the missing half is invisible. **The editor opens with the membership it will replace.** A put replaces both lists, so an editor seeded empty would silently empty a world on an edit that meant to rename it — and it carries the version it read. Faces belonging to no world are reported rather than hidden. Most are, before anyone arranges anything, and a screen listing only arranged faces under-reports what the holder has. `task-surface.json` is synced from vta-sdk 0.34.1 — the version published by VTI#1338, so the snapshot records a surface that exists — and the recorded coverage moves 198 → 201 in the same commit, which is what that guard asks for. Verified on a real build: all three URIs appear in `manager.js` and in no other bundle, which is both halves of the CI guard. core 596/596, extension 479/479, `tsc -b` clean. Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
🛡️ AI Agentic Security Code Review🔎 A manual security review is recommended before merging. Please contact the Security team for specifics and remediation guidance.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The plugin's half of
persona/facet/*, completing the chain: spec #405 →@openvtc/trust-tasks0.17.9 /trust-tasks-rs0.18.9 → VTI #1338 → here.A holder who uses this model for a while does not end up with three faces. They end up with twenty, and a flat list of twenty is a list nobody reads. A world is the arrangement over them — Work, Home, Play.
Three commits: the core client, the palette, the pane.
The delete confirm is the whole screen
A grouping that looks like a folder is assumed to behave like one, so the confirm names what survives before what goes:
A holder who believes Delete takes the faces with it will not press it; one who believes it and is wrong has lost nothing but will never trust the screen again. There is no cascade on the wire and none is implied — the render test asserts both the survival sentence and the absence of any "also delete" copy.
Three more things worth review
A face already elsewhere is greyed before the save. A checkbox that looked available and then failed is a refusal the holder had no way to anticipate.
worldOfFaceexcludes the world being edited — without it a world becomes uneditable the moment it holds anything, which is the same self-clash the agent excludes on its own side.The refusal is matched on the code, and typed on the class that carries one.
placedElsewheretestsinstanceof RelayTaskErrorandcode === "persona/facet/put:faceAlreadyPlaced"— R3.7, never a message. A refusal whose details are missing or half-typed returnsnullrather than an empty list: "0 faces already belong elsewhere" is a claim, and half an answer about where the holder's faces are is worse than none because the missing half is invisible.The editor opens with the membership it will replace. A put replaces both lists, so an editor seeded empty would silently empty a world on an edit that meant to rename it. It carries the
expectedVersionit read.The palette
Eight
--m-world-*tokens in both themes. A world colour is the third categorical set and the first chosen by a person, which is what makes it worth asserting: given a free-form hex, nothing could keep a decorative choice out of the semantic channel — someone names a world "Work", picks red, and every card in it reads as an alarm with no way to discover why.manager-world-colour.test.mtscomputes the distance from the values the stylesheet actually ships, per theme. Closest legitimate pair is 69.6 (sand vs--w-warn, dark) against a threshold of 60. Verified non-vacuous: moving--m-world-clayto#b03d2dfails with "is 9.0 from --w-danger … a holder picking it would have every card in that world read as danger".Guards
manager.jsand in no other bundle.package.no-restated-types.mjscaughtFacetColourderived by indexed access; it is now re-exported from the generated bindings.task-surface.jsonsynced from vta-sdk 0.34.1 — the version #1338 published, so the snapshot records a surface that exists. Recorded coverage 198 → 201 in the same commit, which is what that guard asks for.Verification
core 596/596, extension 479/479 (24 new),
tsc -bclean,npm run buildclean.Not in this PR
Attribute membership in a world — the wire carries
attributeIdsand the client sends it, but the pane only edits faces so far. And the payoff that motivated putting facets on the wire at all:persona/correlation/analyzedistinguishing sharing within a world (intended) from sharing across worlds (the finding worth raising). That is a change to a different spec.